package main

import (
	"flag"
	"net/http"
	"net/url"
	"gopkg.in/cas.v1"
	"net/http/httputil"
	"os"
	"github.com/vinkdong/gox/log"
)


type myHandler struct{}

var MyHandler = &myHandler{}
var casURL string
var validateCookies []string
var cr int
var authenticationType string

func init() {
	validateCookies = make([]string,100000)
	cr = 0
	flag.StringVar(&casURL, "url", "https://login.vinkdong.com/sso/", "CAS server URL")

	authenticationType = os.Getenv("AUTH_TYPE")
	if os.Getenv("CAS_URL") != ""{
		casURL = os.Getenv("CAS_URL")
	}
}

func main() {
	flag.Parse()

	if casURL == "" {
		flag.Usage()
		return
	}

	log.Info("Starting up")

	m := http.NewServeMux()
	m.Handle("/", MyHandler)

	var server = &http.Server{}

	if authenticationType == "cas" {
		url, _ := url.Parse(casURL)
		client := cas.NewClient(&cas.Options{
			URL: url,
		})

		server = &http.Server{
			Addr:    ":9081",
			Handler: client.Handle(m),
		}
	}else {
		server = &http.Server{
			Addr: ":9081",
			Handler: MyHandler,
		}
	}



	if err := server.ListenAndServe(); err != nil {
		log.Infof("Error from HTTP Server: %v", err)
	}

	log.Info("Shutting down")
}

func (h *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !IsAuthenticated(w,r) {
		return
	}

	if r.URL.Path == "/logout" {
		cas.RedirectToLogout(w, r)
		return
	}


	proxyURL := os.Getenv("PROXY_URL")
	origin, _ := url.Parse(proxyURL)
	director := func(req *http.Request) {
		req.Header.Add("X-Forwarded-Host", req.Host)
		req.Header.Add("X-Origin-Host", origin.Host)
		req.URL.Scheme = "http"
		req.URL.Host = origin.Host
	}
	proxy := &httputil.ReverseProxy{Director: director}
	proxy.ServeHTTP(w, r)
}

func IsAuthenticated(w http.ResponseWriter, r *http.Request) bool {

	if CheckCookie(r) {
		return true
	}
	if authenticationType == "basic" {
		return BasicCheck(r)
	}
	if authenticationType == "oauth" {
		return OauthCheck(w, r)
	}
	if authenticationType == "cas" {
		authored := CasCheck(w, r)
		if !authored {
			cas.RedirectToLogin(w, r)
		} else {
			return true
		}
	}
	return false
}

// todo: check validate time
func CheckCookie(r *http.Request) bool {
	var cookie *http.Cookie
	var err error
	if authenticationType == "cas" {
		cookie, err = r.Cookie("_cas_session")
	} else {
		cookie, err = r.Cookie("_auth_session")
	}
	if err != nil {
		return false
	}
	for _, v := range validateCookies {
		if v == cookie.Value {
			return true
		}
	}
	return false
}

